/*
 * R1.c
 *
 *  Created on: Sep 20, 2013
 *      Authors: Joseph DeLong, Justin Hamric, Alex Newcomer, Alex Bouvy
 */

#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "mpx_supt.h"
#include "defines.h"

int commhand(void);
void date(char* input_tok[6], int command_args);
int help(int argc, char *argv[6]);
int ls(void);
int r_exit(int *exit);
void version(void);

/*
 * main function
 * This is the meat and potatoes of the Appaloosa OS. Everything gets run through here.
 * parameters: NOTHING
 * returns: Integer representing normal operation/termination (0) or an error code (non-zero)
 */
int main(void) {
	sys_init(MODULE_R1);
	version();
	//your initialization routines
	commhand();
	//your cleanup commmands
	sys_exit();
	return 0;
}

/*
 * commhand
 * Written by Alex Bouvy
 * Command Handler for Appaloosa OS
 * parameters: NONE
 * returns: Integer representing normal termination (0), or an error code (non-zero)
 */
int commhand(void) {
	char prompt[3] = "$$>";

	//------------comm literals----------------
	char c1[3]="ls\0";
	char c2[5]="date\0";
	char c3[5]="exit\0";
	char c4[5]="help\0";
	char c5[8]="version\0";
	//------------/comm literals---------------

	char input[256];
	char command[256];
	char* input_tok[6];
	int bufferSize = 256;
	int promptLength = 3;
	int gallop = 1; //set this horse to moving!
	int stringSize; //COMPILER IS NOT CORRECT, THIS VARIABLE IS USED
	int command_args=0;
	int max_args = 6;
	int i, j;
	int daysInFebruary;
	int foundACharacter = 0;
	//loop until user enters the exit command
	while(gallop) { //while still kicking up dust

		command_args=0;
		//print the prompt to the terminal
		promptLength = 3;
		sys_req(2,1, prompt, &promptLength);
		stringSize = sys_req(1, 1, input, &bufferSize);

		input_tok[0] = strtok(input," ");
		if(!strcmp(input_tok[0],"\n")){
			continue;
		}
		else{
			for(i=1;i<max_args;i++){
				input_tok[i]=strtok(NULL," ");
				if(input_tok[i]==NULL) break;
				else command_args = i;
			}
		}

		//hacky fix for tokenization
	        if(command_args==0){
	                strxfrm(input_tok[0],input_tok[0], strlen(input_tok[0]));
	                strcat(input_tok[0],"\0");
	        } 

		//hacky space for other tokenization issue
	        if(command_args==1){
	                if(!(strcmp(input_tok[1],"\n"))){
	                        command_args=0;
	                        input_tok[1] = NULL;
	                }
	        }

		//error handling
		if(!(strcmp(input_tok[0],c1))) {
			if(command_args>0){
				printf("Command %s does not accept arguments.\n",c1);
			}
			else ls();
		}
		else if(!(strcmp(input_tok[0],c2))){
			date(input_tok, command_args);
		}
		else if(!(strcmp(input_tok[0],c3))) {
			if(command_args>0){
				printf("Command %s does not accept arguments.\n",c3);
			}
			else r_exit(&gallop);
		}
		else if(!(strcmp(input_tok[0],c4))) {
			help(command_args, input_tok);
		}
		else if(!(strcmp(input_tok[0],c5))) {
			if(command_args>0){
				printf("Command %s does not accept arguments.\n",c5);
			}
			else version();
		}
		else printf("Command '%s' not recognized\n",input_tok[0]);
	}
	return 0;
}

/*	Date function
 *	Written by : Alex Newcomer
 *		Command: date (-s yyyy mm dd)
 *			If the command, date, is submitted to the terminal, the date is displayed. 
 *			If the command is submitted with the -s flag and an 8 digit number, if the date is valid, the system date will be set to the provided date
 *					If the date submitted is not valid, a message will be sent to the terminal saying so.
 *					
 */
 
 //notes: linker errors
	//fixed by deleting the project and recreating
	
 
 typedef struct date_record {
	int day;
	int month;
	int year;
} date_record;
 
void date(char* input_tok[6], int command_args){
	int i, j;
	int swapper;
	int daysInFebruary;
	int foundACharacter = 0;
	date_record currentDate, newDate;
	
				if(command_args == 4){
				//error check
				if(abs((strncmp(input_tok[1], "-s", 2)))){
					// user entered invalid first arg
					printf("date -> First argument is an invalid switch.\n");
				} else if(!(strncmp(input_tok[1], "-s", 2))){
				//Alex's 9/19/2013 fixing the digit detection issue
				foundACharacter = 0;
				for(j=2; j < 5; j++){ 
					for(i=0; i < strlen(input_tok[j]); i++){
						if(isalpha(input_tok[j][i])){
							foundACharacter = 1;
						}
					}
				}
				if(foundACharacter){
					printf("date -> You must enter digits not characters.\n");
				} 
				//end Alex 9/19/2013
				else
				
					//check for yyyy(2) mm(3) dd(4), valid, not leapyear.
					if(atoi(input_tok[3]) > 12 || atoi(input_tok[3]) < 1){
						//month too big
						printf("date -> too many months\n");
					} else {
						//months and years are OK, check valid days
						//if february
						if(atoi(input_tok[3]) == 2){
							int leap = 0;
							if(atoi(input_tok[2])%400 == 0){
								leap = 1;
							} else if (atoi(input_tok[2])%100 == 0){
								leap = 0;
							} else if(atoi(input_tok[2])%4 == 0){
								leap = 1;
							} else {
								leap = 0;
							}
							if(leap){
								daysInFebruary = 29;
							} else {
								daysInFebruary = 28;
							}
							if(atoi(input_tok[4]) <= daysInFebruary){
								//call date
								date(input_tok, command_args);
							} else {
								//exit with error (leap year)
								printf("date -> leap year violation\n");
							}


						} else {//not february
							switch(atoi(input_tok[3])){
							case 1: case 3: case 5: case 7: case 8: case 10: case 12: 
								if((atoi(input_tok[4]) <= 31) && ( strlen(input_tok[2]) < 6) ){
									//set date
									newDate.month = atoi(input_tok[4]);
									newDate.year = atoi(input_tok[2]);
									newDate.day = atoi(input_tok[3]);
									sys_set_date(&newDate);
								} else {
									printf("date -> input error\n");
								}								
								break;
							case 4: case 6: case 9: case 11:
								if(( atoi(input_tok[4]) <= 30 ) && ( strlen(input_tok[2]) < 6)){
									//set date
									newDate.month = atoi(input_tok[4]);
									newDate.year = atoi(input_tok[2]);
									newDate.day = atoi(input_tok[3]);
									sys_set_date(&newDate);

								} else {
									printf("date -> your days are invalid\n");
								}
								break;
							}
						}
					}
				}
				//date(input_tok, command_args);
			} else if(command_args != 0){
				printf("date -> You have entered the wrong number of arguments\n");
			} else { //no args, display the date!
						sys_get_date(&currentDate);
						printf("%d, %d, %d\n", currentDate.day, currentDate.month, currentDate.year);
			}
}

/*
 * HELP command function
 * Written by Joseph DeLong
 * parameter argc: Integer representing the number of command arguments passed in
 * parameter argv: Pointer to an array of character strings representing the specific command(s) the USER is requesting help for
 * returns 0 if all went well or another integer, depending on the appropriate error code
 */
int help(int argc, char *argv[6]) {
	int returnVal = 0, goodInput = 0, i;
	if(argc < 1 || strcmp(argv[0],"\0") == 0) {
		printf( "You have invoked the HELP command. For more specific help, type HELP [CMD],\nwhere [CMD] is the command you would like help for.\n\n"
				"COMMANDS:\t| Description\n"
				"________________|_______________________________________________________\n"
				"date\t\t| Display/Set the current system date\n"
				"exit\t\t| Exit the system\n"
				"ls\t\t| Display the contents of the Present Working Directory\n"
				"version\t\t| Display the current version of the OS\n"
				"\n" );
		goodInput = 1;
	}
	else {
		if(strncmp(argv[1],"carrot",6) == 0) {
			printf("This has something to do with getting on Appaloosa's good side. Maybe she will let you ride her?\n");
			goodInput = 1;
		}
		if(strncmp(argv[1],"clear",5) == 0) {
			printf("This command clears the screen.\n");
			goodInput = 1;
		}
		if(strncmp(argv[1],"date",4) == 0) {
			printf( "To show the current date, use date.\n"
					"To set the system date, use date -s YYYY MM DD.\n"
					"You can enter negative years, just in case you are in BC.\n"
					"Months must be between 1 and 12.\n"
					"Days must not exceed their respective months, leapyears are included.\n");
			goodInput = 1;
		}
		if(strncmp(argv[1],"exit",4) == 0) {
			printf("This command will exit the Appaloosa OS. Make sure you have saved your work before exiting.\n");
			goodInput = 1;
		}
		if(strncmp(argv[1], "help",4) == 0) {
			printf("Yes, this is the help command.\n");
			goodInput = 1;
		}
		if(strncmp(argv[1],"ls",2) == 0) {
			printf("This command displays the contents of the Current Directory.\n");
			goodInput = 1;
		}
		if(strncmp(argv[1],"version",7) == 0) {
			printf("This command shows the version and developer information for the current version of the Appaloosa OS.\n");
			goodInput = 1;
		}
		if(goodInput == 0) {
			printf("You have requested help for a non-existant command: %s\n",argv[1]);
			returnVal = -56712; //placeholder for error code return (if we are going to do this)
		}
	}
	return returnVal;
}

/*
 * DIRECTORY function
 * Written by Justin Hamric
 * This function prints out the name and size (in bytes) of all files
 * found in the current directory.
*/
 int ls(void){

	char name_buf[20]; //can return a file name of length up to 20
	int buf_size = 40;
	long file_size_p; // size of returned file in bytes
	//int end_of_file = 1;
	//int holder = 1;

	//printf("In LS.\n");

	sys_open_dir("\0");
	/*
	holder = sys_get_entry(name_buf, buf_size, &file_size_p);
	printf("holder is %d at the start.\n", holder);
	*/
	while(sys_get_entry(name_buf, buf_size, &file_size_p) != -113){
		printf("%s of size %ld bytes.\n", name_buf, file_size_p);
	}

	sys_close_dir();
	/*
	while(end_of_file){
		holder = sys_get_entry(name_buf, buf_size, &file_size_p);
		if(holder == -113){
			printf("Nothing remaining in directory.\n");
			sys_close_dir();
			end_of_file = 0;
		}
		else{
			printf("%s of size %ld bytes.\n", name_buf, file_size_p);
		}
	}
	*/
	return 0;
 }
 
 /*
  * EXIT function
  * Written by Alex Bouvy
  * 
  */
int r_exit(int *exit){

	char question[19] = "Really exit? (y/n)\n";
	char input_buffer[256];
	char original_input[256];
	char* input[6];
	int qlength = 19;
	int bufferSize = 256;
	int i;
	int command_args = 0;

	sys_req(2,1, question, &qlength);
	sys_req(1, 1, input_buffer, &bufferSize);
	
	strcpy(original_input,input_buffer);
	strxfrm(original_input,original_input, strlen(original_input));
	input[0] = strtok(input_buffer," ");
	for(i=1;i<6;i++){
		input[i]=strtok(NULL," ");
		if(input[i]==NULL) break;
		else command_args = i;
	}

	if(strlen(input[0])>1){
		strxfrm(input[0],input[0], strlen(input[0]));
	}
	strcat(input[0],"\0");

	//hacky fix for other tokenization issue
	if(command_args==1){
		if(!(strcmp(input[1],"\n"))){
	        	command_args=0;
	        	input[1] = NULL;
	        }
	}
	
	if(command_args>0){
		printf("'%s' is not valid.\n",original_input);
	}
	else if(!(strcmp(input[0],"Y\0"))) {
		*exit = 0;
	}
	else if(!(strcmp(input[0],"y\0"))) {
		*exit = 0;
	}
	else if(!(strcmp(input[0],"N\0"))) {
		//do nothing
	}
	else if(!(strcmp(input[0],"n\0"))) {
		//do nothing
	}
	else printf("'%s' is not valid.\n",input[0]);
	return 0;
}

/*
 * VERSION function
 * Written by Joseph DeLong
 * parameter argCount Integer representing the number of arguments passed to this function
 * parameter argVals Pointer to a character pointer containing all parameters passed to this function
 * return Pointer to a string of characters containing VERSION_INFO
 */
void version(void) {
	printf("%s\n",VERSION_INFO);
}